<template><div><h2 id="行为" tabindex="-1"><a class="header-anchor" href="#行为"><span>行为</span></a></h2>
<p>行为是 <code v-pre>yii\base\Behavior</code> 或其子类的实例。行为，也称为 <a href="http://zh.wikipedia.org/wiki/Mixin" target="_blank" rel="noopener noreferrer">mixins</a>，可以无须改变类继承关系即可增强一个已有的 <code v-pre>yii\base\Component</code> 组件类功能。当行为附加到组件后，它将“注入”它的方法和属性到组件，然后可以像访问组件内定义的方法和属性一样访问它们。此外，行为通过组件能响应被触发的 <a href="https://learnku.com/docs/yii-framework/2.0.x/event/12070" target="_blank" rel="noopener noreferrer">事件</a>，从而自定义或调整组件正常执行的代码。</p>
<h2 id="定义行为" tabindex="-1"><a class="header-anchor" href="#定义行为"><span>定义行为</span></a></h2>
<p>要定义行为，通过继承 <code v-pre>yii\base\Behavior</code> 或其子类来建立一个类。如：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">namespace</span> <span class="token package">app<span class="token punctuation">\</span>components</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>base<span class="token punctuation">\</span>Behavior</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">MyBehavior</span> <span class="token keyword">extends</span> <span class="token class-name">Behavior</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token variable">$prop1</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">private</span> <span class="token variable">$_prop2</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">getProp2</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">_prop2</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">setProp2</span><span class="token punctuation">(</span><span class="token variable">$value</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">_prop2</span> <span class="token operator">=</span> <span class="token variable">$value</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">foo</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>以上代码定义了行为类 <code v-pre>app\components\MyBehavior</code> 并为要附加行为的组件提供了两个属性 <code v-pre>prop1</code> 、<code v-pre>prop2</code> 和一个方法 <code v-pre>foo()</code> 。注意属性 <code v-pre>prop2</code> 是通过 getter <code v-pre>getProp2()</code> 和 setter <code v-pre>setProp2()</code> 定义的。能这样用是因为 <code v-pre>yii\base\Object</code> 是 <code v-pre>yii\base\Behavior</code> 的祖先类，此祖先类支持用 getter 和 setter 方法定义 <a href="https://learnku.com/docs/yii-framework/2.0.x/attribute/12069" target="_blank" rel="noopener noreferrer">属性</a></p>
<p>因为这是一个行为类，当它附加到一个组件时，该组件也将具有 <code v-pre>prop1</code> 和 <code v-pre>prop2</code> 属性和 <code v-pre>foo()</code> 方法。</p>
<blockquote>
<p>Tip: 在行为内部可以通过 [[yii\base\Behavior::owner]] 属性访问行为已附加的组件。</p>
</blockquote>
<blockquote>
<p>Note: 如果 [[yii\base\Behavior:😗*get()]] 和或 [[yii\base\Behavior:😗*set()]] 行为方法被覆盖，则需要覆盖 [[yii\base\Behavior::canGetProperty()]] 和或 [[yii\base\Behavior::canSetProperty()]]。</p>
</blockquote>
<h2 id="处理事件" tabindex="-1"><a class="header-anchor" href="#处理事件"><span>处理事件</span></a></h2>
<p>如果要让行为响应对应组件的事件触发，就应覆写 [[yii\base\Behavior::events()]] 方法，如：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">namespace</span> <span class="token package">app<span class="token punctuation">\</span>components</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>db<span class="token punctuation">\</span>ActiveRecord</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>base<span class="token punctuation">\</span>Behavior</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">MyBehavior</span> <span class="token keyword">extends</span> <span class="token class-name">Behavior</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 其它代码</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">events</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">            <span class="token class-name static-context">ActiveRecord</span><span class="token operator">::</span><span class="token constant">EVENT_BEFORE_VALIDATE</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'beforeValidate'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">beforeValidate</span><span class="token punctuation">(</span><span class="token variable">$event</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// 处理器方法逻辑</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>[[yii\base\Behavior::events()]] 方法返回事件列表和相应的处理器。上例声明了 [[yii\db\ActiveRecord::EVENT_BEFORE_VALIDATE]] 事件和它的处理器 <code v-pre>beforeValidate()</code> 。当指定一个事件处理器时，要使用以下格式之一：</p>
<ul>
<li>指向行为类的方法名的字符串，如上例所示；</li>
<li>对象或类名和方法名的数组，如 <code v-pre>[$object, 'methodName']</code>；</li>
<li>匿名方法。</li>
</ul>
<p>处理器的格式如下，其中 <code v-pre>$event</code> 指向事件参数。关于事件的更多细节请参考 <a href="https://learnku.com/docs/yii-framework/2.0.x/event/12070" target="_blank" rel="noopener noreferrer">事件</a>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$event</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="附加行为" tabindex="-1"><a class="header-anchor" href="#附加行为"><span>附加行为</span></a></h2>
<p>可以静态或动态地附加行为到 <code v-pre>yii\base\Component</code> 组件。前者在实践中更常见。</p>
<p>要静态附加行为，覆写行为要附加的组件类的 [[yii\base\Component::behaviors()]] 方法即可。[[yii\base\Component::behaviors()]] 方法应该返回行为 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/basic-configs.md" target="_blank" rel="noopener noreferrer">配置</a> 列表。每个行为配置可以是行为类名也可以是配置数组。如：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">namespace</span> <span class="token package">app<span class="token punctuation">\</span>models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>db<span class="token punctuation">\</span>ActiveRecord</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">app<span class="token punctuation">\</span>components<span class="token punctuation">\</span>MyBehavior</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">ActiveRecord</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">behaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">            <span class="token comment">// 匿名行为，只有行为类名</span></span>
<span class="line">            <span class="token class-name static-context">MyBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line"></span>
<span class="line">            <span class="token comment">// 命名行为，只有行为类名</span></span>
<span class="line">            <span class="token string single-quoted-string">'myBehavior2'</span> <span class="token operator">=></span> <span class="token class-name static-context">MyBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line"></span>
<span class="line">            <span class="token comment">// 匿名行为，配置数组</span></span>
<span class="line">            <span class="token punctuation">[</span></span>
<span class="line">                <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token class-name static-context">MyBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token string single-quoted-string">'prop1'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'value1'</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token string single-quoted-string">'prop2'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'value2'</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"></span>
<span class="line">            <span class="token comment">// 命名行为，配置数组</span></span>
<span class="line">            <span class="token string single-quoted-string">'myBehavior4'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">                <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token class-name static-context">MyBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token string single-quoted-string">'prop1'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'value1'</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token string single-quoted-string">'prop2'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'value2'</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token punctuation">]</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>通过指定行为配置数组相应的键可以给行为关联一个名称。这种行为称为 <strong>命名行为</strong>。上例中，有两个命名行为：<code v-pre>myBehavior2</code> 和 <code v-pre>myBehavior4</code> 。如果行为没有指定名称就是 <strong>匿名行为</strong>。</p>
<p>要动态附加行为，在对应组件里调用 [[yii\base\Component::attachBehavior()]] 方法即可，如：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">app<span class="token punctuation">\</span>components<span class="token punctuation">\</span>MyBehavior</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 附加行为对象</span></span>
<span class="line"><span class="token variable">$component</span><span class="token operator">-></span><span class="token function">attachBehavior</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'myBehavior1'</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">MyBehavior</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 附加行为类</span></span>
<span class="line"><span class="token variable">$component</span><span class="token operator">-></span><span class="token function">attachBehavior</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'myBehavior2'</span><span class="token punctuation">,</span> <span class="token class-name static-context">MyBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 附加配置数组</span></span>
<span class="line"><span class="token variable">$component</span><span class="token operator">-></span><span class="token function">attachBehavior</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'myBehavior3'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token class-name static-context">MyBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'prop1'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'value1'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'prop2'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'value2'</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>可以通过 [[yii\base\Component::attachBehaviors()]] 方法一次附加多个行为：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$component</span><span class="token operator">-></span><span class="token function">attachBehaviors</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'myBehavior1'</span> <span class="token operator">=></span> <span class="token keyword">new</span> <span class="token class-name">MyBehavior</span><span class="token punctuation">,</span>  <span class="token comment">// 命名行为</span></span>
<span class="line">    <span class="token class-name static-context">MyBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span>          <span class="token comment">// 匿名行为</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>还可以通过 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/concept-configurations.md" target="_blank" rel="noopener noreferrer">配置</a> 去附加行为：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'as myBehavior2'</span> <span class="token operator">=></span> <span class="token class-name static-context">MyBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line"></span>
<span class="line">    <span class="token string single-quoted-string">'as myBehavior3'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token class-name static-context">MyBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'prop1'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'value1'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'prop2'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'value2'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>详情请参考 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/concept-configurations.md#configuration-format" target="_blank" rel="noopener noreferrer">配置</a> 章节。</p>
<h2 id="使用行为" tabindex="-1"><a class="header-anchor" href="#使用行为"><span>使用行为</span></a></h2>
<p>使用行为，必须像前文描述的一样先把它附加到 <code v-pre>yii\base\Component</code> 类或其子类。一旦行为附加到组件，就可以直接使用它。</p>
<p>行为附加到组件后，可以通过组件访问一个行为的 <strong>公共</strong> 成员变量 或 getter 和 setter 方法定义的属性：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token comment">// "prop1" 是定义在行为类的属性</span></span>
<span class="line"><span class="token keyword">echo</span> <span class="token variable">$component</span><span class="token operator">-></span><span class="token property">prop1</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token variable">$component</span><span class="token operator">-></span><span class="token property">prop1</span> <span class="token operator">=</span> <span class="token variable">$value</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>类似地也可以调用行为的 <strong>公共</strong> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token comment">// foo() 是定义在行为类的公共方法</span></span>
<span class="line"><span class="token variable">$component</span><span class="token operator">-></span><span class="token function">foo</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>如你所见，尽管 <code v-pre>$component</code> 未定义 <code v-pre>prop1</code> 和 <code v-pre>foo()</code> ，它们用起来也像组件自己定义的一样。</p>
<p>如果两个行为都定义了一样的属性或方法，并且它们都附加到同一个组件，那么 <strong>首先</strong> 附加上的行为在属性或方法被访问时有优先权。</p>
<p>附加行为到组件时的命名行为，可以使用这个名称来访问行为对象，如下所示：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$behavior</span> <span class="token operator">=</span> <span class="token variable">$component</span><span class="token operator">-></span><span class="token function">getBehavior</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'myBehavior'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>也能获取附加到这个组件的所有行为：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$behaviors</span> <span class="token operator">=</span> <span class="token variable">$component</span><span class="token operator">-></span><span class="token function">getBehaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2 id="移除行为" tabindex="-1"><a class="header-anchor" href="#移除行为"><span>移除行为</span></a></h2>
<p>要移除行为，可以调用 [[yii\base\Component::detachBehavior()]] 方法用行为相关联的名字实现：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$component</span><span class="token operator">-></span><span class="token function">detachBehavior</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'myBehavior1'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>也可以移除 <em>全部</em> 行为：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$component</span><span class="token operator">-></span><span class="token function">detachBehaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2 id="内置行为" tabindex="-1"><a class="header-anchor" href="#内置行为"><span>内置行为</span></a></h2>
<p>Yii 有几种内置行为可用：</p>
<h3 id="属性行为" tabindex="-1"><a class="header-anchor" href="#属性行为"><span>属性行为</span></a></h3>
<p><code v-pre>yii\behaviors\AttributeBehavior</code> 这个行为，在发生特定事件时自动为 ActiveRecord 对象的一个或多个属性指定一个指定的值。</p>
<p>要使用该行为，请配置 <code v-pre>attributes</code> 属性，该属性应指定需要更新的属性列表，以及应该触发更新的相应事件。然后，用一个 PHP 可调用对象来配置 <code v-pre>value</code> 属性，该对象的返回值将被用来分配给当前属性。例如：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>behaviors<span class="token punctuation">\</span>AttributeBehavior</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">behaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token class-name static-context">AttributeBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token comment">// 可以只定义 insert 或 update 之一，缺省的那个表示不执行写表</span></span>
<span class="line">            <span class="token string single-quoted-string">'attributes'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">                <span class="token comment">// insert 表的时候</span></span>
<span class="line">                <span class="token class-name static-context">ActiveRecord</span><span class="token operator">::</span><span class="token constant">EVENT_BEFORE_INSERT</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'attribute1'</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token comment">// update 表的时候</span></span>
<span class="line">                <span class="token class-name static-context">ActiveRecord</span><span class="token operator">::</span><span class="token constant">EVENT_BEFORE_UPDATE</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'attribute2'</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token string single-quoted-string">'value'</span> <span class="token operator">=></span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$event</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                <span class="token keyword">return</span> <span class="token string single-quoted-string">'some value'</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>由于属性值将由该行为自动设置，它们通常不是用户输入，因此不应该被验证，也就是说，它们不应该出现在模型的 [[yii\base\Model::rules()] 方法中。</p>
<h3 id="时间戳行为" tabindex="-1"><a class="header-anchor" href="#时间戳行为"><span>时间戳行为</span></a></h3>
<p><code v-pre>yii\behaviors\TimestampBehavior</code> 这个行为，支持在 <code v-pre>yii\db\ActiveRecord</code> 活动记录存储时，自动更新它的时间戳属性，通常是创建时间和更新时间，它是 <code v-pre>yii\behaviors\AttributeBehavior</code> 行为的子类，要使它，请在你的 ActiveRecord 类中插入以下代码：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>behaviors<span class="token punctuation">\</span>TimestampBehavior</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">behaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token class-name static-context">TimestampBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>再完整一些，如下：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">namespace</span> <span class="token package">app<span class="token punctuation">\</span>models<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>db<span class="token punctuation">\</span>ActiveRecord</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>behaviors<span class="token punctuation">\</span>TimestampBehavior</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">ActiveRecord</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">behaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">            <span class="token punctuation">[</span></span>
<span class="line">                <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token class-name static-context">TimestampBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token string single-quoted-string">'attributes'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">                    <span class="token class-name static-context">ActiveRecord</span><span class="token operator">::</span><span class="token constant">EVENT_BEFORE_INSERT</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'created_at'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'updated_at'</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">                    <span class="token class-name static-context">ActiveRecord</span><span class="token operator">::</span><span class="token constant">EVENT_BEFORE_UPDATE</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'updated_at'</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token comment">// 如果你想用 datetime 代替 UNIX 时间戳:</span></span>
<span class="line">                <span class="token comment">// 'value' => new Expression('NOW()'),</span></span>
<span class="line">            <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>默认情况下，当关联的 AR 对象被 insert 时，该行为将用当前时间戳填充 <code v-pre>created_at</code> 和 <code v-pre>updated_at</code> 属性，当 AR 对象被 update 时，它将用时间戳填充 <code v-pre>updated_at</code> 属性。时间戳值由 <code v-pre>time()</code> 获取。</p>
<p>由于属性值将由该行为自动设置，它们通常不是用户输入，因此不应该被验证，也就是说，<code v-pre>created_at</code> 和 <code v-pre>updated_at</code> 不应该出现在模型的 [[yii\base\Model::rules()] 方法中。</p>
<p>对于以上使用 MySQL 数据库的实现，请事先声明列（<code v-pre>created_at</code>, <code v-pre>updated_at</code>）为 int(11) 类型来存储 UNIX 时间戳。</p>
<p>有了以上这段代码，如果你有一个 <code v-pre>User</code> 对象并且试图保存它，你会发现它的 <code v-pre>created_at</code> 和 <code v-pre>updated_at</code> 被当前的 UNIX 时间戳自动填充：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$user</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">User</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token property">email</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'test@example.com'</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">save</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">echo</span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token property">created_at</span><span class="token punctuation">;</span>  <span class="token comment">// 显示当前时间戳</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你的属性名不同，或想使用其他方式来计算时间戳，你可以配置 <code v-pre>createdAtAttribute</code>、<code v-pre>updatedAtAttribute</code> 和 <code v-pre>value</code> 属性，如下所示:</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>db<span class="token punctuation">\</span>Expression</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">behaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token class-name static-context">TimestampBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token string single-quoted-string">'createdAtAttribute'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'create_time'</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token string single-quoted-string">'updatedAtAttribute'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'update_time'</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token string single-quoted-string">'value'</span> <span class="token operator">=></span> <span class="token keyword">new</span> <span class="token class-name">Expression</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'NOW()'</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你像上面的例子一样，使用一个 <code v-pre>yii\db\Expression</code> 对象，该属性将不保存时间戳值，而是在记录保存之后的 Expression 对象本身。之后，如果你需要 DB 的值，你应该调用记录的 <code v-pre>\yii\db\ActiveRecord::refresh()</code> 方法。</p>
<p>该行为还提供了一个名为 <code v-pre>yii\behaviors\TimestampBehavior::touch()</code> 的方法，允许您将当前的时间戳分配给指定的属性，并将它们保存到数据库中。例如：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$model</span><span class="token operator">-></span><span class="token function">touch</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'creation_time'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="追责行为" tabindex="-1"><a class="header-anchor" href="#追责行为"><span>追责行为</span></a></h3>
<p><code v-pre>yii\behaviors\BlameableBehavior</code> 这个行为，自动用当前用户 ID 填充指定的属性，通常是创建人 ID 和 更新人 ID。它也是 <code v-pre>yii\behaviors\AttributeBehavior</code> 行为的子类，要使用它，可以在 ActiveRecord 类中插入以下代码：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>behaviors<span class="token punctuation">\</span>BlameableBehavior</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">behaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token class-name static-context">BlameableBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>默认情况下，当关联的 AR 对象被 insert 时，该行为将用当前用户 ID 填充 <code v-pre>created_by</code> 和 <code v-pre>updated_by</code> 属性，当 AR 对象被 update 时，它将用当前用户 ID 填充 <code v-pre>updated_by</code> 属性。</p>
<p>由于属性值将由该行为自动设置，它们通常不是用户输入，因此不应该被验证，也就是说，<code v-pre>created_by</code> 和 <code v-pre>updated_by</code> 不应该出现在模型的 [[yii\base\Model::rules ()] 方法中。</p>
<p>如果你的属性名不同，你可以配置 <code v-pre>createdByAttribute</code> 和 <code v-pre>updatedByAttribute</code> 属性，如下所示:</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">behaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token class-name static-context">BlameableBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token string single-quoted-string">'createdByAttribute'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'author_id'</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token string single-quoted-string">'updatedByAttribute'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'updater_id'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="seo-url-slug-行为" tabindex="-1"><a class="header-anchor" href="#seo-url-slug-行为"><span>SEO URL Slug 行为</span></a></h3>
<p><code v-pre>yii\behaviors\SluggableBehavior</code> 这个行为，会自动用一个值填充指定的属性，这个值可以在 URL 中作为一个 slug 使用。它也是 <code v-pre>yii\behaviors\AttributeBehavior</code> 行为的子类。</p>
<p>Slug，可以参考 <a href="https://yoast.com/slug/#slug" target="_blank" rel="noopener noreferrer">yoast.com/slug/#slug</a> ，一般是指网页 URL 链接使用 slug 技术，来做 SEO。它是 URL 的一部分，它以一种易于阅读的形式，标识网站上的特定页面。</p>
<blockquote>
<p>Note: 此行为依赖 php-intl 扩展进行音译。如果没有安装，则返回<code v-pre>yii\helpers\Inflector::$transliteration</code> 中定义的来替代。</p>
</blockquote>
<p>要使用该行为，插入以下代码到你的 ActiveRecord 类：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>behaviors<span class="token punctuation">\</span>SluggableBehavior</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">behaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token class-name static-context">SluggableBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token string single-quoted-string">'attribute'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'title'</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token comment">// 'slugAttribute' => 'slug',</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>默认情况下，当相关的 AR 对象被验证时，该行为将可以在 URL 中使用一个 slug 值来填充 <code v-pre>slug</code> 属性。</p>
<p>由于属性值会通过该行为自动设置，它们通常不是用户输入的，因此不应该被验证，也就是说，<code v-pre>slug</code> 属性不应该出现在模型的 [[yii\base\Model::rules()] 方法中。</p>
<p>如果你的属性名不同，可以像下面这样配置 <code v-pre>slugAttribute</code> 属性：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">behaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token class-name static-context">SluggableBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token string single-quoted-string">'slugAttribute'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'alias'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="属性类型转换行为" tabindex="-1"><a class="header-anchor" href="#属性类型转换行为"><span>属性类型转换行为</span></a></h3>
<p>从 2.0.10 版本开始，<code v-pre>yii\behaviors\AttributeTypecastBehavior</code> 这个行为，提供自动模型属性类型转换的能力。</p>
<p>该行为是非常有用的，尤其是在针对无模式数据库，如 MongoDB 、Redis等，且使用 ActiveRecord 的情况下。对于常规的 <code v-pre>yii\db\ActiveRecord</code>，甚至 <code v-pre>yii\base\Model</code>，它也可以派上用场，允许在模型验证后维护严格的属性类型。</p>
<p>该行为应该被附加到 <code v-pre>yii\base\Model</code> 或 <code v-pre>yii\db\BaseActiveRecord</code> 的子类。您应该通过 <code v-pre>attributeTypes</code> 指定确切的属性类型。例如：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>behaviors<span class="token punctuation">\</span>AttributeTypecastBehavior</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Item</span> <span class="token keyword">extends</span> <span class="token class-name class-name-fully-qualified"><span class="token punctuation">\</span>yii<span class="token punctuation">\</span>db<span class="token punctuation">\</span>ActiveRecord</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">behaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'typecast'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">                <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token class-name static-context">AttributeTypecastBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token string single-quoted-string">'attributeTypes'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">                    <span class="token string single-quoted-string">'amount'</span> <span class="token operator">=></span> <span class="token class-name static-context">AttributeTypecastBehavior</span><span class="token operator">::</span><span class="token constant">TYPE_INTEGER</span><span class="token punctuation">,</span></span>
<span class="line">                    <span class="token string single-quoted-string">'price'</span> <span class="token operator">=></span> <span class="token class-name static-context">AttributeTypecastBehavior</span><span class="token operator">::</span><span class="token constant">TYPE_FLOAT</span><span class="token punctuation">,</span></span>
<span class="line">                    <span class="token string single-quoted-string">'is_active'</span> <span class="token operator">=></span> <span class="token class-name static-context">AttributeTypecastBehavior</span><span class="token operator">::</span><span class="token constant">TYPE_BOOLEAN</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token string single-quoted-string">'typecastAfterValidate'</span> <span class="token operator">=></span> <span class="token constant boolean">true</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token string single-quoted-string">'typecastBeforeSave'</span> <span class="token operator">=></span> <span class="token constant boolean">false</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token string single-quoted-string">'typecastAfterFind'</span> <span class="token operator">=></span> <span class="token constant boolean">false</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p>Tip: 当 <code v-pre>attributeTypes</code> 的值将根据所有者验证规则自动检测的情况下，您可以将它置空。下面的例子将自动创建与上面配置相同的 <code v-pre>attributeTypes</code> 值:</p>
</blockquote>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>behaviors<span class="token punctuation">\</span>AttributeTypecastBehavior</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Item</span> <span class="token keyword">extends</span> <span class="token class-name class-name-fully-qualified"><span class="token punctuation">\</span>yii<span class="token punctuation">\</span>db<span class="token punctuation">\</span>ActiveRecord</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">rules</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">            <span class="token punctuation">[</span><span class="token string single-quoted-string">'amount'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'integer'</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token punctuation">[</span><span class="token string single-quoted-string">'price'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'number'</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token punctuation">[</span><span class="token string single-quoted-string">'is_active'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'boolean'</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">behaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'typecast'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">                <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token class-name static-context">AttributeTypecastBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token comment">// 'attributeTypes' will be composed automatically according to `rules()`</span></span>
<span class="line">            <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>该行为允许在以下情况下，自动进行属性类型转换：</p>
<ul>
<li>模型验证成功之后</li>
<li>模型保存（insert 或 update）之前</li>
<li>模型查询（通过查询找到或刷新）之后</li>
</ul>
<p>你可以使用字段 <code v-pre>typecastAfterValidate</code>，<code v-pre>typecastbeforeave</code> 和 <code v-pre>typecastAfterFind</code> 来控制特定情况下的自动类型转换。默认情况下，只有在模型验证之后才会执行类型转换。</p>
<blockquote>
<p>Note：你可以在调用 <code v-pre>yii\behaviors\AttributeTypecastBehavior::typecastAttributes()</code> 方法时手动触发属性类型转换，示例如下：</p>
</blockquote>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$model</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Item</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token variable">$model</span><span class="token operator">-></span><span class="token property">price</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'38.5'</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token variable">$model</span><span class="token operator">-></span><span class="token property">is_active</span> <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token variable">$model</span><span class="token operator">-></span><span class="token function">typecastAttributes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="批量属性行为" tabindex="-1"><a class="header-anchor" href="#批量属性行为"><span>批量属性行为</span></a></h3>
<p>从 2.0.13 版本开始，<code v-pre>yii\behaviors\AttributesBehavior</code> 这个行为，在当某些事件触发时，自动赋值给ActiveRecord 对象的一个或多个属性。</p>
<p>To use AttributesBehavior, configure the [[attributes]] property which should specify the list of attributes that need to be updated and the corresponding events that should trigger the update.<br>
要使用该行为，请配置 <code v-pre>attributes</code> 属性，该属性应指定需要更新的属性列表，以及应该触发更新的相应事件。然后，使用一个 PHP 回调来配置封装数组的值，该返回值将被用于分配给当前属性。例如：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>behaviors<span class="token punctuation">\</span>AttributesBehavior</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">behaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token class-name static-context">AttributesBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token string single-quoted-string">'attributes'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">                <span class="token string single-quoted-string">'attribute1'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">                    <span class="token class-name static-context">ActiveRecord</span><span class="token operator">::</span><span class="token constant">EVENT_BEFORE_INSERT</span> <span class="token operator">=></span> <span class="token keyword">new</span> <span class="token class-name">Expression</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'NOW()'</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
<span class="line">                    <span class="token class-name static-context">ActiveRecord</span><span class="token operator">::</span><span class="token constant">EVENT_BEFORE_UPDATE</span> <span class="token operator">=></span> <span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>Yii</span><span class="token operator">::</span><span class="token variable">$app</span><span class="token operator">-></span><span class="token property">formatter</span><span class="token operator">-></span><span class="token function">asDatetime</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'2017-07-13'</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token string single-quoted-string">'attribute2'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">                    <span class="token class-name static-context">ActiveRecord</span><span class="token operator">::</span><span class="token constant">EVENT_BEFORE_VALIDATE</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token variable">$this</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'storeAttributes'</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">                    <span class="token class-name static-context">ActiveRecord</span><span class="token operator">::</span><span class="token constant">EVENT_AFTER_VALIDATE</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token variable">$this</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'restoreAttributes'</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token string single-quoted-string">'attribute3'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">                    <span class="token class-name static-context">ActiveRecord</span><span class="token operator">::</span><span class="token constant">EVENT_BEFORE_VALIDATE</span> <span class="token operator">=></span> <span class="token variable">$fn2</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token variable">$this</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'getAttribute2'</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">                    <span class="token class-name static-context">ActiveRecord</span><span class="token operator">::</span><span class="token constant">EVENT_AFTER_VALIDATE</span> <span class="token operator">=></span> <span class="token variable">$fn2</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token string single-quoted-string">'attribute4'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">                    <span class="token class-name static-context">ActiveRecord</span><span class="token operator">::</span><span class="token constant">EVENT_BEFORE_DELETE</span> <span class="token operator">=></span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$event</span><span class="token punctuation">,</span> <span class="token variable">$attribute</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                        <span class="token keyword static-context">static</span><span class="token operator">::</span><span class="token function">disabled</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token variable">$event</span><span class="token operator">-></span><span class="token property">isValid</span> <span class="token operator">=</span> <span class="token constant boolean">false</span><span class="token punctuation">;</span></span>
<span class="line">                    <span class="token punctuation">}</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>由于属性值将由该行为自动设置，它们通常不是用户输入，因此不应该被验证，也就是说，它们不应该出现在模型的 [[yii\base\Model::rules()] 方法中。</p>
<h3 id="可缓存小部件行为" tabindex="-1"><a class="header-anchor" href="#可缓存小部件行为"><span>可缓存小部件行为</span></a></h3>
<p>从 2.0.14 版本开始，<code v-pre>yii\behaviors\CacheableWidgetBehavior</code> 这个行为，可以根据指定的持续时间和依赖项，自动缓存小部件内容。</p>
<p>如果应用程序配置了 <code v-pre>cache</code> 缓存组件，该行为可以在没有任何配置的情况下使用。默认情况下，小部件将被缓存 60 秒。</p>
<p>下面的例子将无限期地缓存 posts 小部件，直到 post 被修改：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>behaviors<span class="token punctuation">\</span>CacheableWidgetBehavior</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">behaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token class-name static-context">CacheableWidgetBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token string single-quoted-string">'cacheDuration'</span> <span class="token operator">=></span> <span class="token number">0</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token string single-quoted-string">'cacheDependency'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">                <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'yii\caching\DbDependency'</span><span class="token punctuation">,</span></span>
<span class="line">                <span class="token string single-quoted-string">'sql'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'SELECT MAX(updated_at) FROM posts'</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="乐观锁行为" tabindex="-1"><a class="header-anchor" href="#乐观锁行为"><span>乐观锁行为</span></a></h3>
<p>从 2.0.16 版本开始，<code v-pre>yii\behaviors\OptimisticLockBehavior</code> 这个行为，使用 [[yii\db\BaseActiveRecord::optimisticLock()]] 返回的列名，并自动升级一个模型的锁版本，它也是 yii\behaviors\AttributeBehavior 行为的子类。</p>
<p>乐观锁定允许多个用户访问同一条记录进行编辑，从而避免了潜在的冲突。当用户试图保存一些过期数据的记录时（因为另一个用户修改了数据），一个 <code v-pre>yii\db\StaleObjectException</code> 异常将被抛出，并且跳过更新或删除操作。</p>
<p>要使用该行为，首先按照 [[yii\db\BaseActiveRecord::optimisticLock()] 中列出的步骤启用乐观锁，再从你的 ActiveRecord 类的 [[yii\base\Model::rules()] 方法中移除持有锁版本的列名，然后向其添加以下代码：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">yii<span class="token punctuation">\</span>behaviors<span class="token punctuation">\</span>OptimisticLockBehavior</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">behaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token class-name static-context">OptimisticLockBehavior</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>默认情况下，该行为将使用 [[yii\web\Request::getBodyParam()]] 解析提交的值，或者在任何失败时将其设置为 0，这意味着不包含 version 属性的请求可能实现对实体的首次成功更新，但是从这里开始，任何进一步的尝试都应该失败，除非请求持有预期的版本号。</p>
<p>一旦附加行为，如果版本号不是由 [[yii\web\Request::getBodyParam()] 保存，模型类的内部使用也会失败。扩展您的模型类可能是有用的，通过重写 [[yii\db\BaseActiveRecord::optimisticLock()]] 在父类中启用乐观锁，然后将该行为附加到子类，以至于您可以将父模型绑定到内部使用，同时将持有此行为的子模型连接到负责接收最终用户输入的控制器。</p>
<p>或者，您也可以使用 PHP 回调 配置 <code v-pre>value</code> 属性来实现不同的逻辑。</p>
<p>该行为还提供了一个名为 <code v-pre>upgrade()</code> 的方法，该方法将模型的版本增加 1，当你需要在连接的客户端之间将一个实体标记为陈旧的，并避免任何更改，直到他们再次加载它时，这可能是有用的:</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$model</span><span class="token operator">-></span><span class="token function">upgrade</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2 id="其它行为" tabindex="-1"><a class="header-anchor" href="#其它行为"><span>其它行为</span></a></h2>
<p>有几种外部行为可用：</p>
<ul>
<li><a href="https://github.com/yii2tech/ar-softdelete" target="_blank" rel="noopener noreferrer">yii2tech\ar\softdelete\SoftDeleteBehavior</a> - 提供软删除和软恢复 ActiveRecord 的 方法。即将记录标记为已删除的设置标记或状态。</li>
<li><a href="https://github.com/yii2tech/ar-position" target="_blank" rel="noopener noreferrer">yii2tech\ar\position\PositionBehavior</a> - 允许通过提供重新排序方法来管理整数字段中的记录顺序。</li>
</ul>
<h2 id="比较行为与-trait" tabindex="-1"><a class="header-anchor" href="#比较行为与-trait"><span>比较行为与 Trait</span></a></h2>
<p>虽然行为类似于 <a href="https://www.php.net/manual/zh/language.oop5.traits.php" target="_blank" rel="noopener noreferrer">Trait</a>，它们都将自己的属性和方法“注入”到主类中，但它们在许多方面有所不同。如下所述，他们都有优点和缺点。它们更像互补类而非替代类。</p>
<h3 id="使用行为的原因" tabindex="-1"><a class="header-anchor" href="#使用行为的原因"><span>使用行为的原因</span></a></h3>
<p>行为类像普通类支持继承。另一方面，Trait 可以视为 PHP 语言支持的复制粘贴功能，它不支持继承。</p>
<p>行为无须修改组件类就可动态附加到组件或移除。要使用 Trait，必须修改使用它的类。</p>
<p>行为是可配置的，而 Trait 则不可行。</p>
<p>行为可以通过响应事件来定制组件的代码执行。</p>
<p>当附属于同一组件的不同行为之间可能存在名称冲突时，通过优先考虑附加到该组件的行为，自动解决冲突。由不同 Trait 引起的名称冲突需要通过重命名受影响的属性或方法进行手动解决。</p>
<h3 id="使用-trait-的原因" tabindex="-1"><a class="header-anchor" href="#使用-trait-的原因"><span>使用 Trait 的原因</span></a></h3>
<p>Trait 比行为更有效，因为行为是既需要时间又需要内存的对象。</p>
<p>因为 IDE 是一种本地语言结构，所以它们对 Trait 更友好。</p>
<blockquote>
<p>💖喜欢本文档的，欢迎点赞、收藏、留言或转发，谢谢支持！<br>
作者邮箱：zhuzixian520@126.com，github地址：<a href="https://github.com/zhuzixian520" target="_blank" rel="noopener noreferrer">github.com/zhuzixian520</a></p>
</blockquote>
</div></template>


